package com.xsir.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xsir.common.Result;
import com.xsir.dto.ArticleList;
import com.xsir.dto.ArticleView;
import com.xsir.entity.Article;
import com.xsir.entity.Category;
import com.xsir.entity.Tag;
import com.xsir.service.*;
import com.xsir.util.JwtUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author xsir
 * @date 2020/9/9
 */
@Api(value = "articles", description = "与文章相关的接口")
@RestController
@RequestMapping("articles")
@Slf4j
public class ArticleController {
    /**
     * 已发布
     */
    private final Integer STATUS_PUBLISHED = 0;
    /**
     * 未发布
     */
    private final Integer STATUS_UNPUBLISHED = 1;
    
    @Resource
    private IUserService userService;
    @Resource
    private IArticleService articleService;
    @Resource
    private ICategoryService categoryService;
    @Resource
    private ITagService tagService;
    
    /**
     * 分页查询文章，关键字查询文章
     *
     * @param current 当前页
     * @param size    每页条数
     * @param order   排序方式
     * @param keyword 关键字
     */
    @ApiOperation(value = "分页查询文章，关键字查询文章")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "current", value = "当前页", defaultValue = "1", dataType = "int"),
            @ApiImplicitParam(name = "size", value = "每页条数", defaultValue = "10", dataType = "int"),
            @ApiImplicitParam(name = "order", value = "排序方式(降序)[0：最新，1：最热]", defaultValue = "0", dataType = "int"),
            @ApiImplicitParam(name = "keyword", value = "关键字", dataType = "string")
    })
    @GetMapping
    public Result list(@RequestParam(name = "current", defaultValue = "1", required = false) Integer current,
                       @RequestParam(name = "size", defaultValue = "10", required = false) Integer size,
                       @RequestParam(name = "order", defaultValue = "0", required = false) Integer order,
                       @RequestParam(name = "keyword", required = false) String keyword) {
        QueryWrapper<Article> wrapper = new QueryWrapper<>();
        Page<Article> page = new Page<>(current, size);
        
        // 添加条件
        if (!StringUtils.isEmpty(keyword)) {
            wrapper.like("title", keyword).or().like("summary", keyword);
        }
        wrapper.eq("status", STATUS_PUBLISHED);
        // 默认按时间降序
        wrapper.orderByDesc(order == 0 ? "create_time" : "views");
        
        // 封装结果
        Page<Article> articlePage = articleService.page(page, wrapper);
        ArticleList articleList = new ArticleList(articlePage);
        
        return Result.ok().data(articleList);
    }
    
    /**
     * 获取作者的所有文章
     *
     * @param author 作者
     * @return 结果
     */
    @ApiOperation(value = "查询指定用户的所有文章")
    @GetMapping("/author")
    public Result author(Page<Article> page, @RequestParam("author") String author) {
        Page<Article> articlePage = articleService.page(page, new QueryWrapper<Article>().eq("author", author));
        if (articlePage == null) {
            return Result.ok("博主还没有发布任何内容！");
        }
        List<Article> articles = articlePage.getRecords();
        long total = articlePage.getTotal();
        Map<String, Object> data = new HashMap<>(2);
        data.put("list", articles);
        data.put("total", total);
        return Result.ok().data(data);
    }
    
    /**
     * 获取指定文章
     *
     * @param articleId 文章id
     * @return 结果
     */
    @ApiOperation(value = "查询指定文章")
    @GetMapping("/{id}")
    public Result getOne(@PathVariable(name = "id") Integer articleId) {
        Article article = articleService.getById(articleId);
        Category category = categoryService.getByArticle(articleId);
        List<Tag> tags = tagService.getByArticle(articleId);
        Map<String, Object> data = new HashMap<>(4);
        data.put("article", article);
        data.put("category", category);
        data.put("tags", tags);
        return Result.ok().data(data);
    }
    
    /**
     * 发布文章
     *
     * @param articleView
     * @return
     */
    @ApiOperation(value = "发布文章或保存草稿")
    @ApiImplicitParam(dataTypeClass = ArticleView.class)
    @RequiresRoles("user")
    @PostMapping(value = "/publish", produces = "application/json;charset=utf-8")
    public Result publish(@RequestBody ArticleView articleView) {
        // 从token中获取当前用户编号
        String token = (String) SecurityUtils.getSubject().getPrincipal();
        Long uid = Long.valueOf((Integer) JwtUtil.decode(token).get("uid"));
        articleService.saveOrUpdate(articleView.getArticle());
        // 发布文章
        boolean b = articleService.publish(uid, articleView);
        return b ? Result.ok() : Result.error();
    }
    
    /**
     * 查询我的文章(已发布或未发布)
     *
     * @param page
     * @param published
     * @return
     */
    @ApiOperation(value = "查询我的文章(已发布或未发布)")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(dataTypeClass = Page.class),
            @ApiImplicitParam(name = "published", value = "true:已发布,false:未发布", defaultValue = "true",
                    dataType = "boolean", dataTypeClass = Boolean.class)
    })
    @RequiresRoles("user")
    @GetMapping("/mine")
    public Result mine(Page<Article> page, @RequestParam(name = "published", defaultValue = "true") Boolean published) {
        QueryWrapper<Article> wrapper = new QueryWrapper<>();
        wrapper.eq("status", published ? STATUS_PUBLISHED : STATUS_UNPUBLISHED);
        Page<Article> articlePage = articleService.page(page, wrapper);
        ArticleList articleList = new ArticleList(articlePage);
        
        return Result.ok().data(articleList);
    }
    
    /**
     * 删除指定文章
     * @param articleId 文章编号
     */
    @ApiOperation(value = "删除指定文章")
    @ApiImplicitParam(name = "articleId", value = "文章编号")
    @RequiresRoles("user")
    @DeleteMapping("/delete/{id}")
    public Result delete(@PathVariable(name = "id") Integer articleId) {
        articleService.delete(articleId);
        return Result.ok();
    }
}
